{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import os\n",
    "\n",
    "data_path = 'f:\\\\anaconda3\\\\lib\\\\site-packages\\\\cv2\\\\data'\n",
    "data_path = r'D:\\SoftInstall\\Anacoda3\\Lib\\site-packages\\cv2\\data'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.chdir(data_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 驱动器 D 中的卷是 Data\n",
      " 卷的序列号是 BC8A-BFB6\n",
      "\n",
      " D:\\SoftInstall\\Anacoda3\\Lib\\site-packages\\cv2\\data 的目录\n",
      "\n",
      "2020/04/04  16:18           341,406 haarcascade_eye.xml\n",
      "2020/04/04  16:18           601,661 haarcascade_eye_tree_eyeglasses.xml\n",
      "2020/04/04  16:18           411,388 haarcascade_frontalcatface.xml\n",
      "2020/04/04  16:18           382,918 haarcascade_frontalcatface_extended.xml\n",
      "2020/04/04  16:18           676,709 haarcascade_frontalface_alt.xml\n",
      "2020/04/04  16:18         2,689,040 haarcascade_frontalface_alt_tree.xml\n",
      "2020/04/04  16:18           540,616 haarcascade_frontalface_alt2.xml\n",
      "2020/04/04  16:18           930,127 haarcascade_frontalface_default.xml\n",
      "2020/04/04  16:18           476,827 haarcascade_fullbody.xml\n",
      "2020/04/04  16:18           195,369 haarcascade_lefteye_2splits.xml\n",
      "2020/04/04  16:18            47,775 haarcascade_licence_plate_rus_16stages.xml\n",
      "2020/04/04  16:18           395,322 haarcascade_lowerbody.xml\n",
      "2020/04/04  16:18           828,514 haarcascade_profileface.xml\n",
      "2020/04/04  16:18           196,170 haarcascade_righteye_2splits.xml\n",
      "2020/04/04  16:18            75,482 haarcascade_russian_plate_number.xml\n",
      "2020/04/04  16:18           188,506 haarcascade_smile.xml\n",
      "2020/04/04  16:18           785,819 haarcascade_upperbody.xml\n",
      "              17 个文件      9,763,649 字节\n",
      "               0 个目录 233,547,767,808 可用字节\n"
     ]
    }
   ],
   "source": [
    "ls *.xml"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实时检测人脸"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def crop_pic(img, x, y, w, h):\n",
    "    cv2.imshow('face', img[x:x + w, y:y + h, :])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "cap = cv2.VideoCapture(0) \n",
    "face_cascade = cv2.CascadeClassifier(os.path.join(data_path, 'haarcascade_frontalface_default.xml')) # 加载人脸特征库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "while(True):\n",
    "    ret, frame = cap.read() # 读取一帧的图像\n",
    "    if not ret:\n",
    "        print('failed to read camera data.')\n",
    "        break\n",
    "\n",
    "    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 转灰\n",
    "\n",
    "    faces = face_cascade.detectMultiScale(gray, scaleFactor = 3, minNeighbors = 5, minSize = (5, 5)) # 检测人脸\n",
    "    for(x, y, w, h) in faces:\n",
    "        crop_pic(frame, x, y, w, h)\n",
    "        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 用矩形圈出人脸\n",
    "        \n",
    "    cv2.imshow('Face Recognition', frame)\n",
    "    if cv2.waitKey(1) & 0xFF == ord('q'):\n",
    "        break\n",
    "\n",
    "cap.release() # 释放摄像头\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里主要说下minNeighbors,minSize,maxSize.这三个参数.\n",
    "通过这三个参数可以控制检测的精确度.\n",
    "- minNeighbors 值越大,检测的准确度越高,不过耗时也越久.酌情调整.\n",
    "- minSize 可以根据Screen 尺寸的一定比例来设置,别设置太小,不然会有一些错误干扰结果.\n",
    "- maxSize 最大可检测尺寸,酌情调整."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 动态区域检测"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 背景相减\n",
    "\n",
    "### MOG2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "\n",
    "# 可选参数 比如 进行建模场景的时间长度 高斯混合成分的数量-阈值等\n",
    "backSub = cv2.createBackgroundSubtractorMOG2(detectShadows=False)\n",
    "# backSub = cv2.createBackgroundSubtractorKNN()\n",
    "\n",
    "# capture = cv.VideoCapture(cv.saqmples.findFileOrKeep(args.input))\n",
    "capture = cv2.VideoCapture(0) \n",
    "\n",
    "while True:\n",
    "    ret, frame = capture.read()\n",
    "    if frame is None:\n",
    "        break\n",
    "\n",
    "    #update the background model\n",
    "    fgMask = backSub.apply(frame)\n",
    "\n",
    "    #get the frame number and write it on the current frame\n",
    "    cv2.rectangle(frame, (10, 2), (100,20), (255,255,255), -1)\n",
    "    cv2.putText(frame, str(capture.get(cv2.CAP_PROP_POS_FRAMES)), (15, 15),\n",
    "               cv2.FONT_HERSHEY_SIMPLEX, 0.5 , (0,0,0))\n",
    "\n",
    "    #show the current frame and the fg masks\n",
    "    cv2.imshow('Frame', frame)\n",
    "    cv2.imshow('FG Mask', fgMask)\n",
    "\n",
    "    if cv2.waitKey(1) & 0xFF == ord('q'):\n",
    "        break\n",
    "\n",
    "capture.release() # 释放摄像头\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## KNN"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "此算法结合了静态背景图像估计和每个像素的贝叶斯分割。\n",
    "它使用前面很少的图像（默认为前 120 帧）进行背景建模。\n",
    "使用了概率前景估计算法（使用贝叶斯估计鉴定前景）。\n",
    "这是一种自适应的估计，新观察到的对象比旧的对象具有更高的权重，\n",
    "从而对光照变化产生适应。一些形态学操作如开运算闭运算等被用来除去不需要的噪音。\n",
    "在前几帧图像中你会得到一个黑色窗口。对结果进行形态学开运算对与去除噪声很有帮助。\n",
    "\n",
    "```python\n",
    "1.定义1个KNN背景分割器对象\n",
    "2.定义视频对象\n",
    " \n",
    "while True：\n",
    "     \n",
    "    3.一帧帧读取视频\n",
    "    4.计算前景掩码\n",
    "     \n",
    "    5.二值化操作\n",
    "    6.膨胀操作\n",
    " \n",
    "    7.查找轮廓\n",
    "    8.轮廓筛选\n",
    "    9.画出轮廓（在原图像）\n",
    "  \n",
    "    10.显示图像帧，\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 简洁版"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import cv2\n",
    "\n",
    "cap = cv2.VideoCapture(0)\n",
    "# 定义卷积核\n",
    "kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))\n",
    "fgbg = cv2.createBackgroundSubtractorKNN(dist2Threshold=True)\n",
    "\n",
    "while (1):\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:\n",
    "        print('Input Error！输入错误！')\n",
    "        break\n",
    "    fgmask = fgbg.apply(frame)\n",
    "    fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_ELLIPSE, kernel)\n",
    "\n",
    "    cv2.imshow('Frame', frame)\n",
    "    cv2.imshow('FG Mask', fgmask)\n",
    "\n",
    "    if cv2.waitKey(1) & 0xFF == ord('q'):\n",
    "        break\n",
    "\n",
    "cap.release()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 动态区域检测1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "\n",
    "bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)\n",
    "\n",
    "# 2.读取视频\n",
    "camera = cv2.VideoCapture(0)\n",
    "\n",
    "# 定义卷积核圆形,构建一个椭圆形的核\n",
    "kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))\n",
    "\n",
    "while True:\n",
    "    ret, frame = camera.read()\n",
    "\n",
    "    # 3. apply()函数计算了前景掩码\n",
    "    fgmask = bs.apply(frame)\n",
    "\n",
    "    # 4. 获得前景掩码（含有白色值以及阴影的灰色值），通过设定阈值将非白色（244~255）的所有像素都设为0，而不是1；\n",
    "    th = cv2.threshold(fgmask.copy(), 244, 255, cv2.THRESH_BINARY)[1]  # 二值化操作\n",
    "    # 5.膨胀操作\n",
    "    dilated = cv2.dilate(th, kernel, iterations=2)  \n",
    "    # 6. findContours函数参数说明: cv2.RETR_EXTERNAL只检测外轮廓，\n",
    "    # cv2.CHAIN_APPROX_SIMPLE只存储水平，垂直，对角直线的起始点。\n",
    "    contours, hier = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 查找轮廓\n",
    "\n",
    "    for c in contours:  # 从list列表取出每个轮廓\n",
    "        if cv2.contourArea(c) < 400:  # 进行轮廓筛选 轮廓面积小于400 忽略\n",
    "            continue\n",
    "\n",
    "        (x, y, w, h) = cv2.boundingRect(c)\n",
    "        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)\n",
    "\n",
    "    cv2.imshow(\"mog\", fgmask)\n",
    "    cv2.imshow(\"thresh\", th)\n",
    "    cv2.imshow(\"detection\", frame)\n",
    "\n",
    "    if cv2.waitKey(100) & 0xff == ord(\"q\"):\n",
    "        break\n",
    "\n",
    "camera.release()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 动态区域检测2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "\n",
    "\n",
    "camera = cv2.VideoCapture(0)\n",
    "history = 120  # 训练帧数\n",
    "\n",
    "bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)  # 背景减除器，设置阴影检测\n",
    "bs.setHistory(history)\n",
    "\n",
    "frames = 0\n",
    "\n",
    "while True:\n",
    "    res, frame = camera.read()\n",
    "    if not res:\n",
    "        print('Input Error！输入错误！')\n",
    "        break\n",
    "\n",
    "    # 获取 foreground mask\n",
    "    fg_mask = bs.apply(frame)  \n",
    "\n",
    "    if frames < history:\n",
    "        frames += 1\n",
    "        continue\n",
    "\n",
    "    # 二值化\n",
    "    th = cv2.threshold(fg_mask.copy(), 244, 255, cv2.THRESH_BINARY)[1]\n",
    "    # 对原始帧进行膨胀去噪\n",
    "    th = cv2.erode(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)), iterations=2)\n",
    "    dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (8, 3)), iterations=2)\n",
    "    # 获取所有检测框\n",
    "    contours, hier = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "    # print(len(contours))\n",
    "\n",
    "    for c in contours:\n",
    "        # 计算矩形框的面积\n",
    "        area = cv2.contourArea(c)\n",
    "        if area >  300:\n",
    "            # 获取矩形框边界坐标\n",
    "            x, y, w, h = cv2.boundingRect(c)\n",
    "            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)\n",
    "\n",
    "    cv2.imshow(\"detection\", frame)\n",
    "    cv2.imshow(\"back\", dilated)\n",
    "    if cv2.waitKey(1) & 0xFF == ord('q'):\n",
    "        break\n",
    "camera.release()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 帧间差分法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**注意：**这种方法十分受光线变化影响"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Open\n",
      "size:(640, 480)\n"
     ]
    }
   ],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "camera = cv2.VideoCapture(0)  # 参数0表示第一个摄像头\n",
    "# 判断视频是否打开\n",
    "if camera.isOpened():\n",
    "    print('Open')\n",
    "else:\n",
    "    print('摄像头未打开')\n",
    "\n",
    "# 测试用,查看视频size\n",
    "size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)),\n",
    "        int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT)))\n",
    "print('size:' + repr(size))\n",
    "\n",
    "es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 4))\n",
    "kernel = np.ones((5, 5), np.uint8)\n",
    "background = None\n",
    "\n",
    "while True:\n",
    "    # 读取视频流\n",
    "    grabbed, frame_lwpCV = camera.read()\n",
    "    # 对帧进行预处理，先转灰度图，再进行高斯滤波。\n",
    "    # 用高斯滤波进行模糊处理，进行处理的原因：每个输入的视频都会因自然震动、光照变化或者摄像头本身等原因而产生噪声。对噪声进行平滑是为了避免在运动和跟踪时将其检测出来。\n",
    "    gray_lwpCV = cv2.cvtColor(frame_lwpCV, cv2.COLOR_BGR2GRAY)\n",
    "    gray_lwpCV = cv2.GaussianBlur(gray_lwpCV, (7, 7), 0)\n",
    "\n",
    "    # 将第一帧设置为整个输入的背景\n",
    "    if background is None:\n",
    "        background = gray_lwpCV\n",
    "        continue\n",
    "    # 对于每个从背景之后读取的帧都会计算其与背景之间的差异，并得到一个差分图（different map）。\n",
    "    # 还需要应用阈值来得到一幅黑白图像，并通过下面代码来膨胀（dilate）图像，从而对孔（hole）和缺陷（imperfection）进行归一化处理\n",
    "    diff = cv2.absdiff(background, gray_lwpCV)\n",
    "    # 二值化阈值处理\n",
    "    diff = cv2.threshold(diff, 148, 255, cv2.THRESH_BINARY)[1]\n",
    "    # 形态学膨胀\n",
    "    diff = cv2.dilate(diff, es, iterations=2)\n",
    "    # 显示矩形框\n",
    "    contours, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL,\n",
    "                                           cv2.CHAIN_APPROX_SIMPLE)\n",
    "    # 该函数计算一幅图像中目标的轮廓\n",
    "    for c in contours:\n",
    "        # 小面积过滤，对于光照不变和噪声低的摄像头可不设定轮廓最小尺寸的阈值\n",
    "        if cv2.contourArea(c) < 400:\n",
    "            continue\n",
    "        (x, y, w, h) = cv2.boundingRect(c)  # 该函数计算矩形的边界框\n",
    "        cv2.rectangle(frame_lwpCV, (x, y), (x + w, y + h), (0, 255, 0), 2)\n",
    "\n",
    "    cv2.imshow('contours', frame_lwpCV)\n",
    "    cv2.imshow('dis', diff)\n",
    "\n",
    "    key = cv2.waitKey(1) & 0xFF\n",
    "    # 按'q'健退出循环\n",
    "    if key == ord('q'):\n",
    "        break\n",
    "\n",
    "camera.release()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 目标跟踪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 手动选择区域\n",
    "\n",
    "[参考](https://www.jianshu.com/p/e0b12a5e9f71)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "from imutils.video import VideoStream\n",
    "from imutils.video import FPS\n",
    "import cv2\n",
    "\n",
    "def main(video, algorithm):\n",
    "    \"\"\" \n",
    "    :param video: 待处理的视频文件\n",
    "    :param algorithm: 指定OpenCV中的跟踪算法\n",
    "    \"\"\"\n",
    "\n",
    "    major_ver, minor_ver, subminor_ver = cv2.__version__.split('.')\n",
    "\n",
    "    # 根据opencv的不同版本，创建跟踪器\n",
    "    if int(major_ver) < 3:\n",
    "        tracker = cv2.Tracker_create(algorithm)\n",
    "    else:\n",
    "        if algorithm == 'BOOSTING':\n",
    "            tracker = cv2.TrackerBoosting_create()\n",
    "        if algorithm == 'MIL':\n",
    "            tracker = cv2.TrackerMIL_create()\n",
    "        if algorithm == 'KCF':\n",
    "            tracker = cv2.TrackerKCF_create()\n",
    "        if algorithm == 'TLD':\n",
    "            tracker = cv2.TrackerTLD_create()\n",
    "        if algorithm == 'MEDIANFLOW':\n",
    "            tracker = cv2.TrackerMedianFlow_create()\n",
    "        if algorithm == 'GOTURN':\n",
    "            tracker = cv2.TrackerGOTURN_create()\n",
    "        if algorithm == \"CSRT\":\n",
    "            tracker = cv2.TrackerCSRT_create()\n",
    "        if algorithm == 'MOSSE':\n",
    "            tracker = cv2.TrackerMOSSE_create()\n",
    "\n",
    "    # 读取视频文件\n",
    "    video_cap = cv2.VideoCapture(video)\n",
    "\n",
    "    # 检查视频文件是否被正确打开\n",
    "    if not video_cap.isOpened():\n",
    "        print(\"Open video failed.\")\n",
    "        sys.exit()\n",
    "\n",
    "    # 读取第一帧数据\n",
    "    ok, frame = video_cap.read()\n",
    "    if not ok:\n",
    "        print('Read video file failed.')\n",
    "        sys.exit()\n",
    "\n",
    "    # 手动选择关注的区域\n",
    "    bbox = cv2.selectROI(\"Frame\", frame, showCrosshair=False)\n",
    "    cv2.destroyWindow('Frame')\n",
    "\n",
    "    # 初始化跟踪器\n",
    "    ok = tracker.init(frame, bbox)\n",
    "    \n",
    "    while True:\n",
    "        # 读取下一帧数据\n",
    "        ok, frame = video_cap.read()\n",
    "        if not ok:\n",
    "            break\n",
    "\n",
    "        # 开始计时器\n",
    "        timer = cv2.getTickCount()\n",
    "\n",
    "        # 更新跟踪器\n",
    "        ok, bbox = tracker.update(frame)\n",
    "\n",
    "        # 计算fps\n",
    "        fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer)\n",
    "\n",
    "        # 画出 bounding box\n",
    "        if ok:\n",
    "            p1 = (int(bbox[0]), int(bbox[1]))\n",
    "            p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))\n",
    "            cv2.rectangle(frame, p1, p2, (255, 0, 0), 2, 1)\n",
    "        else:\n",
    "            # Tracking failure\n",
    "            cv2.putText(frame, \"Tracking failure detected\", (100, 80),\n",
    "                        cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)\n",
    "\n",
    "        # 显示\n",
    "        cv2.putText(frame, algorithm + \" Tracker\", (100, 20),\n",
    "                    cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50, 170, 50), 2)\n",
    "        cv2.putText(frame, \"FPS : \" + str(int(fps)), (100, 50),\n",
    "                    cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50, 170, 50), 2)\n",
    "\n",
    "        cv2.imshow(\"Tracking\", frame)\n",
    "        \n",
    "    key = cv2.waitKey(1) & 0xFF\n",
    "    \n",
    "    if key == ord(\"s\"):\n",
    "        # select the bounding box of the object we want to track (make\n",
    "        # sure you press ENTER or SPACE after selecting the ROI)\n",
    "        bbox = cv2.selectROI(\"Frame\", frame, fromCenter=False,\n",
    "                               showCrosshair=True)\n",
    "\n",
    "        # start OpenCV object tracker using the supplied bounding box\n",
    "        # coordinates, then start the FPS throughput estimator as well\n",
    "        tracker.init(frame, bbox)\n",
    "\n",
    "    # 接收到q键，退出循环\n",
    "    elif key== ord('q'):\n",
    "        sys.exit()\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main(0, 'KCF')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 内置人脸检测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'camera' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-5-55a5c7101c30>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     56\u001b[0m         \u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     57\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 58\u001b[1;33m \u001b[0mcamera\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrelease\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     59\u001b[0m \u001b[0mcv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdestroyAllWindows\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNameError\u001b[0m: name 'camera' is not defined"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import cv2\n",
    "\n",
    "\n",
    "def detectAndDisplay(frame):\n",
    "    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n",
    "    frame_gray = cv2.equalizeHist(frame_gray)\n",
    "\n",
    "    #-- Detect faces\n",
    "    faces = face_cascade.detectMultiScale(frame_gray)\n",
    "    for (x,y,w,h) in faces:\n",
    "        center = (x + w//2, y + h//2)\n",
    "        frame = cv2.ellipse(frame, center, (w//2, h//2), 0, 0, 300, (255, 0, 255), 4)\n",
    "\n",
    "        faceROI = frame_gray[y:y+h,x:x+w]\n",
    "        #-- In each face, detect eyes\n",
    "        eyes = eyes_cascade.detectMultiScale(faceROI)\n",
    "        for (x2,y2,w2,h2) in eyes:\n",
    "            eye_center = (x + x2 + w2//2, y + y2 + h2//2)\n",
    "            radius = int(round((w2 + h2)*0.25))\n",
    "            frame = cv2.circle(frame, eye_center, radius, (255, 0, 0 ), 4)\n",
    "\n",
    "    cv2.imshow('Capture - Face detection', frame)\n",
    "\n",
    "\n",
    "face_cascade_name = os.path.join(data_path, 'haarcascade_frontalface_alt.xml')\n",
    "eyes_cascade_name = os.path.join(data_path, 'haarcascade_eye_tree_eyeglasses.xml')\n",
    "\n",
    "face_cascade = cv2.CascadeClassifier()\n",
    "eyes_cascade = cv2.CascadeClassifier()\n",
    "\n",
    "#-- 1. Load the cascades\n",
    "if not face_cascade.load(cv2.samples.findFile(face_cascade_name)):\n",
    "    print('--(!)Error loading face cascade')\n",
    "    exit(0)\n",
    "if not eyes_cascade.load(cv2.samples.findFile(eyes_cascade_name)):\n",
    "    print('--(!)Error loading eyes cascade')\n",
    "    exit(0)\n",
    "\n",
    "camera_device = 0\n",
    "#-- 2. Read the video stream\n",
    "cap = cv2.VideoCapture(camera_device)\n",
    "if not cap.isOpened:\n",
    "    print('--(!)Error opening video capture')\n",
    "    exit(0)\n",
    "\n",
    "while True:\n",
    "    ret, frame = cap.read()\n",
    "    if frame is None:\n",
    "        print('--(!) No captured frame -- Break!')\n",
    "        break\n",
    "\n",
    "    detectAndDisplay(frame)\n",
    "\n",
    "    if cv2.waitKey(1) & 0xFF == ord('q'):\n",
    "        break\n",
    "\n",
    "camera.release()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [匹配图像位置](https://blog.csdn.net/ns2250225/article/details/60334176/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import aircv as ac"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Administrator\\Desktop\n"
     ]
    }
   ],
   "source": [
    "cd C:\\Users\\Administrator\\Desktop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print circle_center_pos\n",
    "def draw_circle(img, pos, circle_radius, color, line_width):\n",
    "    cv2.circle(img, pos, circle_radius, color, line_width)\n",
    "    cv2.imshow('objDetect', imsrc) \n",
    "    cv2.waitKey(0)\n",
    "    cv2.destroyAllWindows()\n",
    "\n",
    "imsrc = ac.imread('bg.jpg')\n",
    "imobj = ac.imread('obj.png')\n",
    "imsrc.shape, imobj.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# find the match position\n",
    "pos = ac.find_template(imsrc, imobj)\n",
    "pos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "circle_center_pos = tuple(map(int, pos['result']))\n",
    "\n",
    "circle_radius = 50\n",
    "color = (0, 255, 0)\n",
    "line_width = 10\n",
    "\n",
    "# draw circle\n",
    "draw_circle(imsrc, circle_center_pos, circle_radius, color, line_width)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "img = cv2.imread('bg.jpg')\n",
    "img.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pos = [(744, 405), (744, 495), (842, 405), (842, 495)]\n",
    "obj = img[405:495, 744:842 ,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Image.fromarray(obj)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "237.545px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
